home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / lib / unix / select.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  5KB  |  271 lines

  1.  
  2. /*
  3.  *  UNIX/SELECT.C
  4.  *
  5.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  6.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  7.  *    DICE-LICENSE.TXT.
  8.  */
  9.  
  10. #include <exec/types.h>
  11. #include <exec/nodes.h>
  12. #include <exec/ports.h>
  13. #include <dos/dos.h>
  14. #include <sys/types.h>
  15. #include <stdio.h>
  16. #include <fcntl.h>
  17. #include <errno.h>
  18. #include <signal.h>
  19. #include <stdlib.h>
  20. #include <lib/misc.h>
  21. #include <lib/requestfh.h>
  22. #include <lib/waitmsg.h>
  23. #include <devices/timer.h>
  24.  
  25. #include <clib/dos_protos.h>
  26. #include <clib/exec_protos.h>
  27. #include <clib/alib_protos.h>
  28. #include <lists.h>
  29.  
  30. typedef struct MsgPort    MsgPort;
  31. typedef struct Message    Message;
  32. typedef struct Node    Node;
  33. typedef struct List    List;
  34. typedef struct timerequest Iot;
  35.  
  36. typedef struct ReqNode {
  37.     Node    rn_Node;
  38.     short   rn_Fd;
  39.     long    rn_Fh;
  40.     long    rn_Flags;
  41.     Message rn_Message;
  42. } ReqNode;
  43.  
  44. #define RNF_RFDS    0x0001
  45. #define RNF_WFDS    0x0002
  46. #define RNF_RETURNED    0x0100
  47.  
  48. static List FreeList = { (Node *)&FreeList.lh_Tail, NULL, (Node *)&FreeList.lh_Head };
  49. static Iot    Iot0;
  50. static MsgPort    IoSink;
  51.  
  52. void QueueMessage(List *, _IOFDS *, int, long, long);
  53.  
  54. void
  55. _select_exit()
  56. {
  57.     if (Iot0.tr_node.io_Device) {
  58.     CloseDevice((void *)&Iot0);
  59.     Iot0.tr_node.io_Device = NULL;
  60.     }
  61. }
  62.  
  63. int
  64. select(setSize, rfds, wfds, xfds, tv)
  65. int setSize;
  66. fd_set *rfds;
  67. fd_set *wfds;
  68. fd_set *xfds;
  69. struct timeval *tv;
  70. {
  71.     List    actList;
  72.     short   i, j;
  73.     short   sigInt = 0;
  74.     short   iotIp = 0;
  75.  
  76.     if (IoSink.mp_Flags == 0) {
  77.     IoSink.mp_Node.ln_Type = NT_MSGPORT;
  78.     IoSink.mp_Flags = PA_SIGNAL;
  79.     IoSink.mp_SigBit= SIGB_SINGLE;
  80.     IoSink.mp_SigTask = FindTask(NULL);
  81.     NewList(&IoSink.mp_MsgList);
  82.  
  83.     Iot0.tr_node.io_Message.mn_ReplyPort = &IoSink;
  84.     Iot0.tr_node.io_Command = TR_ADDREQUEST;
  85.     OpenDevice("timer.device", UNIT_VBLANK, (void *)&Iot0, 0);
  86.     atexit(_select_exit);
  87.     }
  88.  
  89.     NewList(&actList);
  90.  
  91.     for (i = 0; i < setSize; i += sizeof(fd_mask) * 8) {
  92.     fd_mask mask;
  93.     _IOFDS *d;
  94.  
  95.  
  96.     if (rfds && (mask = rfds->fds_bits[i])) {
  97.         for (j = 0; j < sizeof(fd_mask) * 8; ++j) {
  98.         if ((mask & (1 << j)) && (d = __getfh(i + j))) {
  99.             QueueMessage(&actList, d, i + j, FREQ_RPEND, RNF_RFDS);
  100.         }
  101.         }
  102.     }
  103.     if (wfds && (mask = wfds->fds_bits[i])) {
  104.         for (j = 0; j < sizeof(fd_mask) * 8; ++j) {
  105.         if ((mask & (1 << j)) && (d = __getfh(i + j))) {
  106.             QueueMessage(&actList, d, i + j, FREQ_WAVAIL, RNF_WFDS);
  107.         }
  108.         }
  109.     }
  110.     }
  111.  
  112.     /*
  113.      *    nothing was queued!
  114.      */
  115.  
  116.     if (GetHead(&actList) == NULL) {
  117. #ifdef DEBUG
  118.     puts("ACTLIST EMPTY");
  119. #endif
  120.     errno = 0;
  121.     return(-1);
  122.     }
  123.  
  124.     /*
  125.      *    start timeout
  126.      */
  127.  
  128.     if (tv && (tv->tv_secs || tv->tv_micro)) {
  129. #ifdef DEBUG
  130.     puts("START TIMEOUT");
  131. #endif
  132.     Iot0.tr_time.tv_secs = tv->tv_secs;
  133.     Iot0.tr_time.tv_micro = tv->tv_micro;
  134.     SendIO((void *)&Iot0);
  135.     iotIp = 1;
  136.     }
  137.  
  138.     /*
  139.      *    wait for event(s)
  140.      */
  141.  
  142.     i = 0;
  143.  
  144.     for (;;) {
  145.     {
  146.         ReqNode *rn;
  147.  
  148.         while (rn = (struct ReqNode *)GetMsg(&IoSink)) {
  149.         if ((char *)rn == (char *)&Iot0) {
  150.             tv->tv_secs = 0;
  151.             tv->tv_micro = 0;
  152.             iotIp = 0;
  153. #ifdef DEBUG
  154.             puts("TIMEOUT");
  155. #endif
  156.             continue;
  157.         }
  158. #ifdef DEBUG
  159.         puts("REQ RETURNED");
  160. #endif
  161.         rn = (ReqNode *)((char *)rn - offsetof(ReqNode, rn_Message));
  162.         rn->rn_Flags |= RNF_RETURNED;
  163.         ++i;
  164.         }
  165.     }
  166.     /*
  167.      *  if tv was not NULL and was 0, break out
  168.      */
  169.     if (tv && tv->tv_secs == 0 && tv->tv_micro == 0) {
  170. #ifdef DEBUG
  171.         puts("TIME ENDED");
  172. #endif
  173.         break;
  174.     }
  175.     if (i) {
  176. #ifdef DEBUG
  177.         puts("DESCRIPT FOUND");
  178. #endif
  179.         break;
  180.     }
  181.     {
  182.         long mask = Wait(SIGF_SINGLE | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);
  183.         if (mask & (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D)) {
  184.         sigInt = 1;
  185.         break;
  186.         }
  187.     }
  188.     }
  189.  
  190.     if (iotIp) {
  191.     AbortIO((void *)&Iot0);
  192.     WaitIO((void *)&Iot0);
  193.     }
  194.  
  195.     /*
  196.      *    abort remaining requests, clearing those that have not been returned
  197.      *    (no event pending)
  198.      */
  199.  
  200.     i = 0;
  201.  
  202.     {
  203.     ReqNode *rn;
  204.  
  205.     while (rn = (struct ReqNode *)RemHead(&actList)) {
  206.         if (rn->rn_Message.mn_Node.ln_Type == NT_MESSAGE) {
  207.         if (rn->rn_Flags & RNF_RFDS)
  208.             FD_CLR(rn->rn_Fd, rfds);
  209.         if (rn->rn_Flags & RNF_WFDS)
  210.             FD_CLR(rn->rn_Fd, wfds);
  211.         RequestFH(rn->rn_Fh, &rn->rn_Message, FREQ_ABORT);
  212.         WaitMsg(&rn->rn_Message);
  213.         } else {
  214.         if ((rn->rn_Flags & RNF_RETURNED) == 0)
  215.             WaitMsg(&rn->rn_Message);
  216.         ++i;
  217.         }
  218.         AddTail(&FreeList, &rn->rn_Node);
  219.     }
  220.     }
  221.  
  222.     /*
  223.      *    SIGINT?
  224.      */
  225.  
  226.     if (sigInt) {
  227.     raise(SIGINT);
  228.     if (i == 0) {
  229.         i = -1;
  230.         errno = EINTR;
  231.     }
  232.     } else if (i == 0) {
  233.     i = -1;
  234.     errno = EWOULDBLOCK;
  235.     }
  236.     return(i);
  237. }
  238.  
  239. void
  240. QueueMessage(list, d, fd, how, flags)
  241. List *list;
  242. _IOFDS *d;
  243. int fd;
  244. long how;
  245. long flags;
  246. {
  247.     ReqNode *rn;
  248.  
  249.     if ((rn = (struct ReqNode *)RemHead(&FreeList)) == NULL)
  250.     rn = malloc(sizeof(ReqNode));
  251.     if (rn) {
  252.     rn->rn_Message.mn_ReplyPort = &IoSink;
  253.     rn->rn_Flags = flags;
  254.     rn->rn_Fh = d->fd_Fh;
  255.     rn->rn_Fd = fd;
  256.  
  257.     if (RequestFH(d->fd_Fh, &rn->rn_Message, how)) {
  258. #ifdef DEBUG
  259.         printf("ADDED %d\n", fd);
  260. #endif
  261.         AddTail(list, &rn->rn_Node);
  262.     } else {
  263. #ifdef DEBUG
  264.         printf("NOTSUPPORTED: FD %d\n", fd);
  265. #endif
  266.         AddTail(&FreeList, &rn->rn_Node);
  267.     }
  268.     }
  269. }
  270.  
  271.